using B.S.XZYData.Api.Wrter.Application.Command.WorkReport;
using B.S.XZYData.Domain.ZSH;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.XZYData.Api.Wrter.Application.Handler.WorkReport
{
    /// <summary>
    /// 导出报工数据处理器
    /// </summary>
    public class ExportWorkReportHandler : IRequestHandler<ExportWorkReportCommand, ApiResult<byte[]>>
    {
        private readonly IBaseRepository<Domain.ZSH.WorkReport> _workReportRepo;

        public ExportWorkReportHandler(IBaseRepository<Domain.ZSH.WorkReport> workReportRepo)
        {
            _workReportRepo = workReportRepo;
        }

        public async Task<ApiResult<byte[]>> Handle(ExportWorkReportCommand request, CancellationToken cancellationToken)
        {
            var res = new ApiResult<byte[]>();

            try
            {
                // 构建查询条件
                var query = _workReportRepo.GetAll().Where(x => !x.IsDeleted);

                // 应用筛选条件
                if (!string.IsNullOrWhiteSpace(request.ProcessName))
                {
                    query = query.Where(x => x.ProcessName.Contains(request.ProcessName));
                }

                if (!string.IsNullOrWhiteSpace(request.ProductCode))
                {
                    query = query.Where(x => x.ProductCode.Contains(request.ProductCode));
                }

                if (!string.IsNullOrWhiteSpace(request.ProductName))
                {
                    query = query.Where(x => x.ProductName != null && x.ProductName.Contains(request.ProductName));
                }

                if (request.ProcessStatus.HasValue)
                {
                    query = query.Where(x => (int)x.ProcessStatus == request.ProcessStatus.Value);
                }

                if (!string.IsNullOrWhiteSpace(request.Producer))
                {
                    query = query.Where(x => x.Producer.Contains(request.Producer));
                }

                if (!string.IsNullOrWhiteSpace(request.WorkOrderCode))
                {
                    query = query.Where(x => x.WorkOrderCode.Contains(request.WorkOrderCode));
                }

                if (request.StartDate.HasValue)
                {
                    query = query.Where(x => x.StartTime >= request.StartDate.Value);
                }

                if (request.EndDate.HasValue)
                {
                    query = query.Where(x => x.StartTime <= request.EndDate.Value);
                }

                // 获取数据并排序
                var workReports = query.OrderByDescending(x => x.CreateTime).ToList();

                // 生成Excel文件
                var excelBytes = GenerateExcelFile(workReports);

                res.Code = ApiEnum.Success;
                res.Data = excelBytes;
                res.Msg = "导出成功";
            }
            catch (Exception ex)
            {
                res.Code = ApiEnum.Fail;
                res.Msg = $"导出失败：{ex.Message}";
            }

            return await Task.FromResult(res);
        }

        /// <summary>
        /// 生成Excel文件（使用NPOI）
        /// </summary>
        /// <param name="workReports">报工数据</param>
        /// <returns>Excel文件字节数组</returns>
        private byte[] GenerateExcelFile(List<Domain.ZSH.WorkReport> workReports)
        {
            // 创建工作簿（使用.xlsx格式）
            IWorkbook workbook = new XSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("报工信息");

            // 创建表头样式
            ICellStyle headerStyle = workbook.CreateCellStyle();
            headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
            headerStyle.FillPattern = FillPattern.SolidForeground;
            headerStyle.Alignment = HorizontalAlignment.Center;
            headerStyle.VerticalAlignment = VerticalAlignment.Center;
            
            // 设置字体
            IFont headerFont = workbook.CreateFont();
            headerFont.IsBold = true;
            headerFont.FontHeightInPoints = 12;
            headerStyle.SetFont(headerFont);

            // 设置边框
            headerStyle.BorderTop = BorderStyle.Thin;
            headerStyle.BorderBottom = BorderStyle.Thin;
            headerStyle.BorderLeft = BorderStyle.Thin;
            headerStyle.BorderRight = BorderStyle.Thin;

            // 创建数据样式
            ICellStyle dataStyle = workbook.CreateCellStyle();
            dataStyle.BorderTop = BorderStyle.Thin;
            dataStyle.BorderBottom = BorderStyle.Thin;
            dataStyle.BorderLeft = BorderStyle.Thin;
            dataStyle.BorderRight = BorderStyle.Thin;
            dataStyle.VerticalAlignment = VerticalAlignment.Center;

            // 定义表头
            var headers = new string[]
            {
                "工单编号", "工序名称", "产品编号", "产品名称", "产品规格",
                "报工数量", "单位", "良品数量", "不良品数量", "生产人员",
                "工序状态", "开始时间", "结束时间", "报工工时(小时)", "报工工时(分钟)",
                "标准效率", "实际效率", "达标率(%)", "计价方式", "工资单价",
                "预估工资", "奖励金额", "扣罚金额", "创建时间"
            };

            // 创建表头行
            IRow headerRow = sheet.CreateRow(0);
            headerRow.Height = 400; // 设置行高

            for (int i = 0; i < headers.Length; i++)
            {
                ICell cell = headerRow.CreateCell(i);
                cell.SetCellValue(headers[i]);
                cell.CellStyle = headerStyle;
                
                // 设置列宽
                sheet.SetColumnWidth(i, 4000); // 调整列宽
            }

            // 写入数据
            for (int row = 0; row < workReports.Count; row++)
            {
                var workReport = workReports[row];
                IRow dataRow = sheet.CreateRow(row + 1);
                dataRow.Height = 350; // 设置数据行高

                // 工单编号
                var cell0 = dataRow.CreateCell(0);
                cell0.SetCellValue(workReport.WorkOrderCode ?? "");
                cell0.CellStyle = dataStyle;

                // 工序名称
                var cell1 = dataRow.CreateCell(1);
                cell1.SetCellValue(workReport.ProcessName ?? "");
                cell1.CellStyle = dataStyle;

                // 产品编号
                var cell2 = dataRow.CreateCell(2);
                cell2.SetCellValue(workReport.ProductCode ?? "");
                cell2.CellStyle = dataStyle;

                // 产品名称
                var cell3 = dataRow.CreateCell(3);
                cell3.SetCellValue(workReport.ProductName ?? "");
                cell3.CellStyle = dataStyle;

                // 产品规格
                var cell4 = dataRow.CreateCell(4);
                cell4.SetCellValue(workReport.ProductSpec ?? "");
                cell4.CellStyle = dataStyle;

                // 报工数量
                var cell5 = dataRow.CreateCell(5);
                cell5.SetCellValue(Convert.ToDouble(workReport.ReportQty));
                cell5.CellStyle = dataStyle;

                // 单位
                var cell6 = dataRow.CreateCell(6);
                cell6.SetCellValue(workReport.Unit ?? "");
                cell6.CellStyle = dataStyle;

                // 良品数量
                var cell7 = dataRow.CreateCell(7);
                cell7.SetCellValue(Convert.ToDouble(workReport.GoodQty));
                cell7.CellStyle = dataStyle;

                // 不良品数量
                var cell8 = dataRow.CreateCell(8);
                cell8.SetCellValue(Convert.ToDouble(workReport.DefectiveQty));
                cell8.CellStyle = dataStyle;

                // 生产人员
                var cell9 = dataRow.CreateCell(9);
                cell9.SetCellValue(workReport.Producer ?? "");
                cell9.CellStyle = dataStyle;

                // 工序状态
                var cell10 = dataRow.CreateCell(10);
                cell10.SetCellValue(GetProcessStatusText(workReport.ProcessStatus));
                cell10.CellStyle = dataStyle;

                // 开始时间
                var cell11 = dataRow.CreateCell(11);
                cell11.SetCellValue(workReport.StartTime.ToString("yyyy-MM-dd HH:mm:ss"));
                cell11.CellStyle = dataStyle;

                // 结束时间
                var cell12 = dataRow.CreateCell(12);
                cell12.SetCellValue(workReport.EndTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? "");
                cell12.CellStyle = dataStyle;

                // 报工工时(小时)
                var cell13 = dataRow.CreateCell(13);
                cell13.SetCellValue(Convert.ToDouble(workReport.ReportHours));
                cell13.CellStyle = dataStyle;

                // 报工工时(分钟)
                var cell14 = dataRow.CreateCell(14);
                cell14.SetCellValue(Convert.ToDouble(workReport.ReportMinutes));
                cell14.CellStyle = dataStyle;

                // 标准效率
                var cell15 = dataRow.CreateCell(15);
                cell15.SetCellValue(Convert.ToDouble(workReport.StandardEfficiency));
                cell15.CellStyle = dataStyle;

                // 实际效率
                var cell16 = dataRow.CreateCell(16);
                cell16.SetCellValue(Convert.ToDouble(workReport.ActualEfficiency));
                cell16.CellStyle = dataStyle;

                // 达标率
                var cell17 = dataRow.CreateCell(17);
                cell17.SetCellValue(Convert.ToDouble(workReport.ComplianceRate));
                cell17.CellStyle = dataStyle;

                // 计价方式
                var cell18 = dataRow.CreateCell(18);
                cell18.SetCellValue(GetPricingMethodText(workReport.PricingMethod));
                cell18.CellStyle = dataStyle;

                // 工资单价
                var cell19 = dataRow.CreateCell(19);
                cell19.SetCellValue(Convert.ToDouble(workReport.WageUnitPrice));
                cell19.CellStyle = dataStyle;

                // 预估工资
                var cell20 = dataRow.CreateCell(20);
                cell20.SetCellValue(Convert.ToDouble(workReport.EstimatedWage));
                cell20.CellStyle = dataStyle;

                // 奖励金额
                var cell21 = dataRow.CreateCell(21);
                cell21.SetCellValue(Convert.ToDouble(workReport.BonusAmount));
                cell21.CellStyle = dataStyle;

                // 扣罚金额
                var cell22 = dataRow.CreateCell(22);
                cell22.SetCellValue(Convert.ToDouble(workReport.PenaltyAmount));
                cell22.CellStyle = dataStyle;

                // 创建时间
                var cell23 = dataRow.CreateCell(23);
                cell23.SetCellValue(workReport.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
                cell23.CellStyle = dataStyle;
            }

            // 自动调整列宽
            for (int i = 0; i < headers.Length; i++)
            {
                sheet.AutoSizeColumn(i);
                // 设置最小列宽，防止列宽过小
                if (sheet.GetColumnWidth(i) < 2000)
                {
                    sheet.SetColumnWidth(i, 2000);
                }
                // 设置最大列宽，防止列宽过大
                if (sheet.GetColumnWidth(i) > 8000)
                {
                    sheet.SetColumnWidth(i, 8000);
                }
            }

            // 将工作簿写入内存流
            using (var stream = new MemoryStream())
            {
                workbook.Write(stream);
                workbook.Close();
                return stream.ToArray();
            }
        }

        /// <summary>
        /// 获取工序状态文本
        /// </summary>
        private string GetProcessStatusText(ProcessStatusEnum status)
        {
            return status switch
            {
                ProcessStatusEnum.NotStarted => "未开始",
                ProcessStatusEnum.InProgress => "进行中",
                ProcessStatusEnum.Completed => "已完成",
                _ => "未知"
            };
        }

        /// <summary>
        /// 获取计价方式文本
        /// </summary>
        private string GetPricingMethodText(PricingMethodEnum method)
        {
            return method switch
            {
                PricingMethodEnum.ByPiece => "按件计价",
                PricingMethodEnum.ByHour => "按时计价",
                _ => "未知"
            };
        }
    }
} 